from __future__ import annotations

import os
from typing import TYPE_CHECKING

from .ioquake3Paths import IOQUAKE3_CONFIG, IOQUAKE3_ROMS

if TYPE_CHECKING:
    from collections.abc import Iterable
    from pathlib import Path

    from ...controller import Controllers
    from ...Emulator import Emulator
    from ...types import Resolution


def writeCfgFile(system: Emulator, filename: Path, init_line: str, defaults_to_add: Iterable[str], controls_to_add: Iterable[str], gameResolution: Resolution) -> None:
    if not filename.is_file():
        filename.parent.mkdir(parents=True, exist_ok=True)

        with filename.open('w') as file:
            file.write(init_line)
            for line in defaults_to_add:
                file.write(line)

            file.write(f'seta com_hunkMegs "{system.config.get('ioquake3_mem', '256')}"\n')

            if system.config.core == 'vkquake3':
                file.write(f'seta cl_renderer "{system.config.get("vkquake3_api", "opengl2")}"\n')

            for line in controls_to_add:
                file.write(line)
    else:
        with filename.open('r+') as file:
            lines = file.readlines()
            file.seek(0)
            for line in lines:
                ## Set defaults every time
                # resolution
                if line.startswith('seta r_mode'):
                    line = 'seta r_mode "-1"\n'
                elif line.startswith('seta r_customwidth'):
                    line = f'seta r_customwidth "{gameResolution["width"]}"\n'
                elif line.startswith('seta r_customheight'):
                    line = f'seta r_customheight "{gameResolution["height"]}"\n'
                # controllers
                elif line.startswith('seta in_joystickUseAnalog'):
                    line = 'seta in_joystickUseAnalog "1"\n'
                elif line.startswith('seta in_joystick'):
                    line = 'seta in_joystick "1"\n'
                # network downloads
                elif line.startswith('seta cl_allowDownload'):
                    line = 'seta cl_allowDownload "1"\n'

                ## User options
                # Memory
                elif line.startswith('seta com_hunkMegs'):
                    line = f'seta com_hunkMegs "{system.config.get("ioquake3_mem", "256")}"\n'
                # API
                elif line.startswith('seta cl_renderer'):
                    if system.config.core == 'vkquake3':
                        line = f'seta cl_renderer "{system.config.get("vkquake3_api", "opengl2")}"\n'
                    else:
                        line = ''  # ioquake3 doesn't use this, so remove it if a vkquake3 setting gets added

                file.write(line)

            # Add the missing lines at the end of the file
            for line in defaults_to_add:
                if line not in lines:
                    file.write(line)
            for line in controls_to_add:
                if line not in lines:
                    file.write(line)

def writeCfgFiles(system: Emulator, rom: Path, playersControllers: Controllers, gameResolution: Resolution) -> None:
    # create the cfg files for each quake3 rom / mod folder
    files: list[Path] = []

    # get the immediate subdirectories within rom directory
    subdirectories = next(os.walk(IOQUAKE3_ROMS))[1]

    # add the corresponding config file paths and add them to the `files` list
    for subdirectory in subdirectories:
        config_directory = IOQUAKE3_CONFIG / subdirectory
        config_file = config_directory / "q3config.cfg"
        files.append(config_file)

    init_line = '// generated by quake, do not modify\n'
    # minimum defaults
    defaults_to_add = [
        'seta r_mode "-1"\n',
        f'seta r_customwidth "{gameResolution["width"]}"\n',
        f'seta r_customheight "{gameResolution["height"]}"\n',
        'seta in_joystickUseAnalog "1"\n',
        'seta in_joystick "1"\n',
        'seta cl_allowDownload "1"\n'
    ]

    # basic controller config
    controls_to_add = [
        'bind PAD0_A "+moveup"\n',
        'bind PAD0_X "+movedown"\n',
        'bind PAD0_Y "+button2"\n',
        'bind PAD0_LEFTSHOULDER "weapnext"\n',
        'bind PAD0_RIGHTSHOULDER "weapprev"\n',
        'bind PAD0_LEFTSTICK_LEFT "+moveleft"\n',
        'bind PAD0_LEFTSTICK_RIGHT "+moveright"\n',
        'bind PAD0_LEFTSTICK_UP "+forward"\n',
        'bind PAD0_LEFTSTICK_DOWN "+back"\n',
        'bind PAD0_RIGHTSTICK_LEFT "+left"\n',
        'bind PAD0_RIGHTSTICK_RIGHT "+right"\n',
        'bind PAD0_RIGHTSTICK_UP "+lookup"\n',
        'bind PAD0_RIGHTSTICK_DOWN "+lookdown"\n',
        'bind PAD0_LEFTTRIGGER "+speed"\n',
        'bind PAD0_RIGHTTRIGGER "+attack"\n'
    ]

    for filename in files:
        writeCfgFile(system, filename, init_line, defaults_to_add, controls_to_add, gameResolution)
